package client.admin;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import client.AdminService;
import client.AdminServiceAsync;
import client.RepositoryDTO;
import client.ui.RepositoryEditingDialogBox;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;

public class AdminManager {
	
	private final AdminServiceAsync adminService = (AdminServiceAsync)GWT.create(AdminService.class);
	
	private Map<Long, Integer> repositoryPositionMapping = new HashMap<Long, Integer>();
	
	private final FlexTable ft;

	public AdminManager(FlexTable ft) {
		this.ft = ft;
		refreshAdminScreen();
		//set up a timer for monitoring the state of the repositories
		final Timer refreshTimer = new Timer() {

			@Override
			public void run() {
				refreshAdminScreen();
			}

			
		};
		refreshTimer.scheduleRepeating(10000);
	}
	private void refreshAdminScreen() {
		adminService.getRepositories(new AsyncCallback<List<RepositoryDTO>>() {
			
			public void onFailure(Throwable caught) {
				Window.alert("Unable to refresh repositories becayse :"+caught.getMessage());
			}
			
			public void onSuccess(List<RepositoryDTO> result) {
				for (RepositoryDTO dto : result) {
					draw(dto);
				}
			}
		});
	}
	
	private void draw(final RepositoryDTO dto) {
		final long id = dto.getId();
		//check if we already have this one
		if (repositoryPositionMapping.containsKey(id)) {
			final int tablePosition = repositoryPositionMapping.get(id);
			updateIfDifferent(tablePosition, 0, dto.getName());
			updateIfDifferent(tablePosition, 1, dto.getUrl());
			final CheckBox checkBox = (CheckBox)ft.getWidget(tablePosition, 2);
			if (dto.isEnabled()!=checkBox.isEnabled()) {
				checkBox.setValue(dto.isEnabled());
			}
		} else {
			//add it to the bottom
			final int row = ft.getRowCount();
			ft.setText(row, 0, dto.getName());
			ft.setText(row, 1, dto.getUrl());
			final CheckBox enableDisableCheckbox = new CheckBox("Enabled");
			enableDisableCheckbox.setValue(dto.isEnabled());
			enableDisableCheckbox.addClickHandler(new ClickHandler() {

				public void onClick(ClickEvent event) {
					adminService.updateRepositoryEnabledFlag(dto.getId(), enableDisableCheckbox.getValue(), new AsyncCallback<Void>() {

						public void onFailure(Throwable caught) {
							Window.alert("Unable to change status of repository");
						}

						public void onSuccess(Void result) {
							//nothing to do
							assert true;
						}
						
					});
				}
				
			});
			ft.setWidget(row, 2, enableDisableCheckbox);
			final Button editButton = new Button("Edit");
			editButton.addClickHandler(new ClickHandler() {

				public void onClick(ClickEvent event) {
					final RepositoryEditingDialogBox dialog = new RepositoryEditingDialogBox();
					dialog.addOkClickHandler(new ClickHandler() {

						public void onClick(ClickEvent event) {
							final RepositoryDTO repositoryDTOForUpdate = dialog.getRepository();
							adminService.updateRepository(repositoryDTOForUpdate, new AsyncCallback<Void>() {

								public void onFailure(Throwable caught) {
									Window.alert("The update failed because:"+caught.getMessage());
									dialog.hide();
								}

								public void onSuccess(Void result) {
									ft.setText(row, 0, repositoryDTOForUpdate.getName());
									ft.setText(row, 1, repositoryDTOForUpdate.getUrl());
									dialog.hide();
								}
								
							});
						}
						
					});
					
					adminService.getRepositoryInformation(dto.getId(), new AsyncCallback<RepositoryDTO>() {

						public void onFailure(Throwable caught) {
							Window.alert("Unable to retrieve repository information for "+dto.getId());
						}

						public void onSuccess(RepositoryDTO result) {
							dialog.displayRepository(result);
						}

					});
					dialog.show();
				}

			});
			ft.setWidget(row, 3, editButton);

			
			final Button deleteButton = new Button("Delete");
			deleteButton.addClickHandler(new ClickHandler() {

				public void onClick(ClickEvent event) {
					if (Window.confirm("Do you really want to delete repository '"+dto.getName()+"'?")) {
						Window.alert("Simulated deletion");
						ft.removeRow(repositoryPositionMapping.get(dto.getId()));
					}
				}
			});
			ft.setWidget(row, 4, deleteButton);
			repositoryPositionMapping.put(id, row);
		}
	}
	
	private void updateIfDifferent(final int row, final int column, final String newValue) {
		if (!newValue.equals(ft.getText(row, column))) {
			ft.setText(row, column, newValue);
		}
	}
	
	public void saveNewRepository(final RepositoryDTO repositoryDTO) {
		adminService.saveNewRepository(repositoryDTO, new AsyncCallback<Void>() {

			public void onFailure(Throwable caught) {
				Window.alert("Failed to save new repository because :"+caught.getMessage());
			}

			public void onSuccess(Void result) {
				//add the repository
				//TODO draw(result);
			}
			
		});
	}

	/* public void refresh() {
		adminService.getRepositories(new AsyncCallback<List<RepositoryDTO>>() {

			public void onFailure(Throwable caught) {
				Window.alert("Error while getting repositories:"+caught.getMessage());
			}

			public void onSuccess(List<RepositoryDTO> result) {
				for (int i=0;i<ft.getRowCount();i++) {
					ft.removeRow(i);
				}
				for (final RepositoryDTO dto : result) {
					draw(dto);
				}
			}
		});
	} */

}
